import { PrismaService } from '@/modules/prisma/prisma.service';
import {
  ForbiddenException,
  Injectable,
  NotFoundException,
  ConflictException,
  BadRequestException,
} from '@nestjs/common';
import { newFolderDto, moveFilesDto } from './basic.dto';
import { v4 as uuid } from 'uuid';
import { format, toZonedTime } from 'date-fns-tz';

@Injectable()
export class BasicService {
  constructor(private prisma: PrismaService) {}

  formatDateToEast8(date?: Date | null): string | null {
    if (!date) return null;
    const zonedDate = toZonedTime(date, 'Asia/Shanghai'); // 东八区对应 Asia/Shanghai
    return format(zonedDate, 'yyyy-MM-dd HH:mm', {
      timeZone: 'Asia/Shanghai',
    });
  }

  async newFolder(userId: number, body: newFolderDto) {
    const whereClause = {
      name: body.folderName,
      parentId: body.curFolderId,
      groupId: body.groupId ?? null,
      status: 'active' as const,
    };

    // 个人空间需要验证创建者
    if (!body.groupId) {
      whereClause['creatId'] = userId;
    }

    const existing = await this.prisma.file.findFirst({
      where: whereClause,
      select: { id: true },
    });
    console.log(existing);

    if (existing) {
      throw new ConflictException('当前目录已存在同名文件夹');
    }
    const id = uuid();
    await this.prisma.file.create({
      data: {
        id: id,
        name: body.folderName,
        type: 'folder',
        parentId: body.curFolderId,
        status: 'active',
        creatId: userId,
        groupId: body.groupId!,
      },
    });
    return id;
  }

  async getCloudDocRoot(userId: number) {
    // 1. 查找用户的云文档根目录（假设根目录 name 为 '云文档'）
    const root = await this.prisma.file.findFirst({
      where: {
        creatId: userId,
        name: '云文档',
        type: 'folder',
        parentId: null,
      },
    });

    if (!root) {
      throw new NotFoundException('云文档根目录不存在');
    }

    // 2. 递归获取所有子节点
    const buildTree = async (parentId: string) => {
      const children = await this.prisma.file.findMany({
        where: { parentId, type: 'folder', status: 'active' },
        orderBy: { createdTime: 'asc' }, // 按创建时间排序
      });

      return Promise.all(
        children.map(async (child) => ({
          id: child.id,
          name: child.name,
          children: await buildTree(child.id), // 递归查询子节点
        })),
      );
    };

    return {
      id: root.id,
      name: root.name,
      children: await buildTree(root.id),
    };
  }

  async getFilesByParentId(parentId: string, userId: number) {
    const files = await this.prisma.file.findMany({
      where: { parentId, status: 'active' },
      select: {
        id: true,
        name: true,
        type: true,
        shortId: true,
        FileCreate: {
          select: {
            username: true,
          },
        },
      },
      orderBy: { createdTime: 'asc' },
    });
    // 2. 提取文件ID集合用于批量查询 FileVD
    const fileIds = files.map((file) => file.id);

    // 3. 批量查询每个文件的最近查看/编辑时间
    const fileVDStats = await this.prisma.fileVD.findMany({
      select: {
        fileId: true,
        lastView: true,
        lastEdit: true,
      },
      where: {
        fileId: { in: fileIds },
      },
    });

    // 4. 将统计结果转换为 Map 方便快速查找
    const statsMap = new Map(
      fileVDStats.map((stat) => [
        stat.fileId,
        {
          lastView: this.formatDateToEast8(stat.lastView),
          lastEdit: this.formatDateToEast8(stat.lastEdit),
        },
      ]),
    );

    // 5. 合并数据到最终结果
    return this.extendFileWithCollectStatus(
      files.map((file) => ({
        ...file,
        creator: file.FileCreate.username,
        lastView: statsMap.get(file.id)?.lastView || null,
        lastEdit: statsMap.get(file.id)?.lastEdit || null,
      })),
      userId,
    );
  }

  async renameFile(id: string, newName: string) {
    const file = await this.prisma.file.findUnique({ where: { id: id } });
    if (!file) {
      throw new ForbiddenException('文件不存在');
    }

    return this.prisma.file.update({
      where: { id: id },
      data: { name: newName },
    });
  }

  async temDeleteFile(id: string) {
    const file = await this.prisma.file.findUnique({
      where: { id: id, status: 'active' },
    });
    if (!file) {
      throw new ForbiddenException('文件不存在');
    }

    return await this.prisma.$transaction(async (prisma) => {
      await Promise.all([
        prisma.fileCollect.deleteMany({ where: { fileId: id } }),
        prisma.fileVD.deleteMany({ where: { fileId: id } }),
        prisma.permission.deleteMany({ where: { fileId: id } }),
      ]);

      return prisma.file.update({
        where: { id: id },
        data: {
          status: 'deleted',
          deletedTime: new Date(),
        },
        include: {
          // 返回关联信息（如果需要）
          permissions: true,
        },
      });
    });
  }

  async restoreFile(id: string) {
    const file = await this.prisma.file.findUnique({ where: { id: id } });
    if (!file) {
      throw new ForbiddenException('文件不存在');
    }
    return this.prisma.file.update({
      where: { id: id },
      data: { status: 'active' },
    });
  }

  async trashFile(userId: number) {
    const res = await this.prisma.file.findMany({
      where: {
        creatId: userId,
        status: 'deleted',
      },
      select: {
        id: true,
        name: true,
        type: true,
        shortId: true,
        deletedTime: true, // 可选字段也需要调整
      },
      orderBy: { deletedTime: 'desc' },
    });
    return res.map((item) => {
      // 强制类型断言：将对象标记为 any 以修改属性类型
      const modifiedItem: any = { ...item };
      modifiedItem.deletedTime = this.formatDateToEast8(item.deletedTime);
      return modifiedItem as typeof item & { deletedTime: string | null }; // 类型合并
    });
  }

  async moveFile(body: moveFilesDto) {
    const targetFolder = await this.prisma.file.findUnique({
      where: { id: body.newParent },
    });
    if (!targetFolder || targetFolder.type !== 'folder') {
      throw new BadRequestException('目标文件夹不存在或类型错误');
    }

    for (const fileId of body.fileIds) {
      if (body.newParent) {
        const isCircular = await this.checkCircularDependency(
          fileId,
          body.newParent,
        );
        if (isCircular) {
          throw new BadRequestException('不能将文件移动到自身或其子目录');
        }
      }

      await this.prisma.file.update({
        where: { id: fileId },
        data: { parentId: body.newParent },
      });
    }

    return 'ok';
  }

  private async checkCircularDependency(
    sourceId: string,
    targetId: string,
  ): Promise<boolean> {
    let currentId: string | null = targetId;
    while (currentId) {
      if (currentId === sourceId) return true;
      const parent = await this.prisma.file.findUnique({
        where: { id: currentId },
        select: { parentId: true },
      });
      currentId = parent?.parentId;
    }
    return false;
  }

  async collectList(userId: number) {
    const collects = await this.prisma.fileCollect.findMany({
      where: {
        userId,
        fileCollect: {
          status: 'active',
        },
      },
      select: {
        userId: true,
        fileId: true,
        fileCollect: {
          select: {
            name: true,
            type: true,
            shortId: true,
            ViewEdit: {
              select: {
                lastView: true,
                lastEdit: true,
              },
              where: { userId }, // 只取当前用户的记录
              orderBy: { lastView: 'desc' },
              take: 1,
            },
          },
        },
      },
      orderBy: {
        createdAt: 'desc',
      },
    });
    // 转换数据结构
    return collects.map((item) => ({
      userId: item.userId,
      fileId: item.fileId,
      name: item.fileCollect.name,
      type: item.fileCollect.type,
      shortId: item.fileCollect.shortId,
      lastView: this.formatDateToEast8(
        item.fileCollect.ViewEdit[0]?.lastView || null,
      ),
      lastEdit: this.formatDateToEast8(
        item.fileCollect.ViewEdit[0]?.lastEdit || null,
      ),
    }));
  }

  async collectFile(userId: number, fileId: string) {
    const existing = await this.prisma.fileCollect.findUnique({
      where: { userId_fileId: { userId, fileId } },
    });

    if (existing) {
      throw new ConflictException('文件已收藏');
    }

    await this.prisma.fileCollect.create({
      data: { userId, fileId },
    });
    return 'ok';
  }

  async unCollectFile(userId: number, fileId: string) {
    await this.prisma.fileCollect.delete({
      where: { userId_fileId: { userId, fileId } },
    });
    return 'ok';
  }

  async deleteFile(userId: number, id: string) {}

  private async extendFileWithCollectStatus(files: any[], userId: number) {
    // 获取所有文件的收藏状态
    const collectedFiles = await this.prisma.fileCollect.findMany({
      where: {
        userId,
        fileId: { in: files.map((f) => f.id) },
      },
      select: { fileId: true },
    });

    const collectedFileIds = new Set(collectedFiles.map((f) => f.fileId));

    return files.map((file) => ({
      ...file,
      collected: collectedFileIds.has(file.id),
    }));
  }
}
